﻿namespace FrameWork.Lib.HTML
{
    using System;
    using System.ComponentModel;
    using System.Text;

    public class HtmlElement : HtmlNode
    {
        protected HtmlAttributeCollection mAttributes;
        protected bool mIsExplicitlyTerminated;
        protected bool mIsTerminated;
        protected string mName;
        protected HtmlNodeCollection mNodes;

        public HtmlElement(string name)
        {
            this.mNodes = new HtmlNodeCollection(this);
            this.mAttributes = new HtmlAttributeCollection(this);
            this.mName = name;
            this.mIsTerminated = false;
        }

        public override string ToString()
        {
            string str = "<" + this.mName;
            foreach (HtmlAttribute attribute in this.Attributes)
            {
                str = str + " " + attribute.ToString();
            }
            return (str + ">");
        }

        [Category("General"), Description("The set of attributes associated with this element")]
        public HtmlAttributeCollection Attributes
        {
            get
            {
                return this.mAttributes;
            }
        }

        [Category("Output")]
        public override string HTML
        {
            get
            {
                StringBuilder builder = new StringBuilder();
                builder.Append("<" + this.mName);
                foreach (HtmlAttribute attribute in this.Attributes)
                {
                    builder.Append(" " + attribute.HTML);
                }
                if (this.Nodes.Count > 0)
                {
                    builder.Append(">");
                    foreach (HtmlNode node in this.Nodes)
                    {
                        builder.Append(node.HTML);
                    }
                    builder.Append("</" + this.mName + ">");
                }
                else if (this.IsExplicitlyTerminated)
                {
                    builder.Append("></" + this.mName + ">");
                }
                else if (this.IsTerminated)
                {
                    builder.Append("/>");
                }
                else
                {
                    builder.Append(">");
                }
                return builder.ToString();
            }
        }

        internal bool IsExplicitlyTerminated
        {
            get
            {
                return this.mIsExplicitlyTerminated;
            }
            set
            {
                this.mIsExplicitlyTerminated = value;
            }
        }

        internal bool IsTerminated
        {
            get
            {
                if (this.Nodes.Count > 0)
                {
                    return false;
                }
                return (this.mIsTerminated | this.mIsExplicitlyTerminated);
            }
            set
            {
                this.mIsTerminated = value;
            }
        }

        [Category("General"), Description("The name of the tag/element")]
        public string Name
        {
            get
            {
                return this.mName;
            }
            set
            {
                this.mName = value;
            }
        }

        [Category("General"), Description("The set of child nodes")]
        public HtmlNodeCollection Nodes
        {
            get
            {
                if (base.IsText())
                {
                    throw new InvalidOperationException("An HtmlText node does not have child nodes");
                }
                return this.mNodes;
            }
        }

        internal bool NoEscaping
        {
            get
            {
                return ("script".Equals(this.Name.ToLower()) || "style".Equals(this.Name.ToLower()));
            }
        }

        [Description("A concatination of all the text associated with this element"), Category("General")]
        public string Text
        {
            get
            {
                StringBuilder builder = new StringBuilder();
                foreach (HtmlNode node in this.Nodes)
                {
                    if (node is HtmlText)
                    {
                        builder.Append(((HtmlText) node).Text);
                    }
                }
                return builder.ToString();
            }
        }

        [Category("Output")]
        public override string XHTML
        {
            get
            {
                if ("html".Equals(this.mName) && (this.Attributes["xmlns"] == null))
                {
                    this.Attributes.Add(new HtmlAttribute("xmlns", "http://www.w3.org/1999/xhtml"));
                }
                StringBuilder builder = new StringBuilder();
                builder.Append("<" + this.mName.ToLower());
                foreach (HtmlAttribute attribute in this.Attributes)
                {
                    builder.Append(" " + attribute.XHTML);
                }
                if (this.IsTerminated)
                {
                    builder.Append("/>");
                }
                else if (this.Nodes.Count > 0)
                {
                    builder.Append(">");
                    foreach (HtmlNode node in this.Nodes)
                    {
                        builder.Append(node.XHTML);
                    }
                    builder.Append("</" + this.mName.ToLower() + ">");
                }
                else
                {
                    builder.Append("/>");
                }
                return builder.ToString();
            }
        }
    }
}

